/* 
 * File:   bop.hpp
 * Author: gustavo
 *
 * Created on August 10, 2012, 1:47 AM
 */

#ifndef MBOP_HPP
#define	MBOP_HPP

#include <stdio.h>
#include <stdlib.h>

/**
 * This function prints a matrix M at console.
 * @param m - number of rows of the matrix.
 * @param n - number of columns of the matrix.
 * @param M - pointer to the first matrix element.
 * @param stm - matrix stride. Number of elements from one row to the next row
 * in the memory. This value corresponds to the distance (sizeof(*M) * stm) in bytes.
 */
template <typename T> inline void m_print(int m, int n, T * M, int stm) {

	int r, c;

	if (!M) {
		printf("Null.\n\n");
		return;
	}

	for (r = 0; r < m; r++) {
		for (c = 0; c < n; c++) {
			//printf("%4.4f\t", (double) ( abs(*M) < __eps) ? 0.0 : *M );
			printf("%4.3f\t", (float) *M);
			M++;
		}
		printf("\n");
		M += (stm - n);
	}
	printf("\n\n");
}

/**
 * This function copies a matrix to another.
 * 
 * @param m
 * @param n
 * @param Orig
 * @param sto
 * @param Dest
 * @param std
 */
template <typename T> inline void m_copy(int m, int n, const T * Orig, int sto, T * Dest, int std) {

	int r, c;

	for (r = 0; r < m; r++) {
		for (c = 0; c < n; c++) {
			*Dest = *Orig;
			Orig++;
			Dest++;
		}
		Orig += (sto - n);
		Dest += (std - n);
	}
}

/**
 * Conversion between types
 * @param m
 * @param n
 * @param A
 * @param sta
 * @param C
 * @param stc
 */
template <typename T1, typename T2> inline void m_copy(int m, int n, const T1 * Orig, int sto, T2 * Dest, int std) {

	int r, c;

	for (r = 0; r < m; r++) {
		for (c = 0; c < n; c++) {
			*Dest = T2(*Orig);
			Orig++;
			Dest++;
		}
		Orig += (sto - n);
		Dest += (std - n);
	}
}

/**
 * 
 * @param m
 * @param n
 * @param A
 * @param sta
 * @param r1
 * @param r2
 */
template <typename T> inline void m_rows_exchange(int m, int n, T * A, int sta, int r1, int r2) {

	T tmp;
	int r, c;

	T * a1 = A + r1 * sta;
	T * a2 = A + r2 * sta;

	for (c = 0; c < n; c++) {

		tmp = *a1;
		*a1 = *a2;
		*a2 = tmp;
		a1++;
		a2++;
	}

}

/**
 * 
 * @param m
 * @param n
 * @param A
 * @param sta
 * @param c1
 * @param c2
 */
template <typename T> inline void m_columns_exchange(int m, int n, T * A, int sta, int c1, int c2) {

	T tmp;
	int r, c;

	T * a1 = A + c1;
	T * a2 = A + c2;

	for (r = 0; r < m; r++) {

		tmp = *a1;
		*a1 = *a2;
		*a2 = tmp;

		a1 += sta;
		a2 += sta;
	}

}

/**
 * This function fill the matrix A with the value of <code>val</code>.
 * @param m
 * @param n
 * @param A
 * @param sta
 * @param val
 */
template <typename T> inline void m_set(int m, int n, T * A, int sta, T val) {

	int r, c;

	for (r = 0; r < m; r++) {
		for (c = 0; c < n; c++) {
			*A = val;
			A++;
		}
		A += (sta - n);
	}
}

/**
 * This function fill the matrix A with the value of <code>val</code>.
 * @param m
 * @param n
 * @param A
 * @param sta
 * @param val
 */
template <typename T> inline void m_set_rand(int m, int n, T * A, int sta) {

	int r, c;

	for (r = 0; r < m; r++) {
		for (c = 0; c < n; c++) {
			*A = (T) rand() / (T) RAND_MAX;
			A++;
		}
		A += (sta - n);
	}
}

/**
 * This function fills the diagonal of a matrix A with val.
 * @param m - dimension of A.
 * @param A - pointer to the first matrix element.
 * @param sta - stride of A.
 */
template <typename T> inline void m_set_diag(int m, T * A, int sta, T val) {
	int r, c;
	T * Ai;

	Ai = A;
	for (r = 0; r < m; r++) {
		for (c = 0; c < m; c++) {
			if (r == c) *Ai = val;
			Ai++;
		}
		Ai += (sta - m);
	}

}




#endif	/* MBOP_HPP */

